package io.summer.basis.excepts;

import java.util.stream.Collectors;

import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import io.summer.basis.api.ApiCode;
import io.summer.basis.api.ApiResponse;
import io.summer.basis.core.MyApplicationContext;
import lombok.extern.slf4j.Slf4j;

/**
 * @author Moonlight
 */
@RestControllerAdvice
@Slf4j
public class MyExceptionHandler extends MyApplicationContext {
  @ExceptionHandler(Throwable.class)
  @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
  public ApiResponse<?> handleException(Throwable ex) {
    printException(ex);
    return ApiResponse.response(ApiCode.INTERNAL_SERVER_ERROR, isProd() ? null : ex.getMessage());
  }

  @ExceptionHandler(AppException.class)
  @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
  public ApiResponse<?> handleAppException(AppException ex) {
    printException(ex);
    return ApiResponse.response(ex);
  }

  @ExceptionHandler(BizException.class)
  //reason 好像会引起sendError把错误指向ErrorController
  @ResponseStatus(value = HttpStatus.OK, reason = "业务异常是用户知晓并根据处理逻辑产生的异常")
  public ApiResponse<?> handleBizException(BizException ex) {
    printException(ex);
    return ApiResponse.response(ex);
  }

  @ExceptionHandler(DaoException.class)
  @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
  public ApiResponse<?> handleDaoException(DaoException ex) {
    printException(ex);
    return ApiResponse.response(ex);
  }

  @ExceptionHandler(MethodArgumentNotValidException.class)
  @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "parameter not expected")
  public ApiResponse<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
    printException(ex);
    String errMsg = ex.getBindingResult().getFieldErrors().stream()
      .map(err -> err.getField() + ":" + err.getDefaultMessage()).collect(Collectors.joining(";"));
    return ApiResponse.response(HttpStatus.BAD_REQUEST.value(), errMsg);
  }

  private void printException(Throwable t) {
    log.error("global Exception=>", t);
  }
}
